import json
from datetime import datetime
from typing import Any, Optional

from pydantic import BaseModel, Field, model_validator, ConfigDict
from typing_extensions import Self

from app.models.base import SQLBaseModel, IdType
from app.models.user import BaseUser
from app.utils.decorators.optional import optional
from app.utils.validate import (
    validate_phone_number,
    validate_password,
    validate_username, validate_email, validate_account,
)
from .base_schema import LoginAccountType
from ..utils.model_converter import ModelConverter


class UserCreate(BaseUser):
    password: Optional[str] = Field(default=None, description="密码")
    confirm_password: Optional[str]= Field(default=None, description="确认密码")
    address: Optional[list[str]]= Field(default=None, description="地址")

    @model_validator(mode="after")
    def validate_model(self)->Self:
        validate_username(self.username)
        validate_password(self.password,self.confirm_password)
        validate_phone_number(self.phone_number)
        validate_email(self.email)
        return self


@optional(without_fields=["id"])
class UserUpdate(UserCreate):
    id: IdType

    @model_validator(mode="after")
    def validate_model(self)->Self:
        validate_username(self.username) if self.username else None
        validate_password(self.password,self.confirm_password) if self.password else None
        validate_phone_number(self.phone_number) if self.phone_number else None
        validate_email(str(self.email)) if self.email else None
        return self


class UserOut(SQLBaseModel, BaseUser):
    model_config = ConfigDict(from_attributes=True)

    address: Optional[list[str]]= Field(default=None, description="地址")

    last_login_datetime: Optional[datetime] = Field(
        default=None, description="最后登录时间"
    )

    role_ids: Optional[list[IdType]] = Field(
        default=None, description="用户具有的角色ID"
    )
    device_ids: Optional[list[IdType]] = Field(
        default=None, description="用户具有的设备ID"
    )
    auth_keys: Optional[list[str]]  = Field(
        default=None, description="用户具有的权限键"
    )

    @model_validator(mode="before")  # 在模型验证前处理数据
    @classmethod
    def extract_fields(cls, data: Any) -> Any:
        result = ModelConverter.extract_multiple_in_model_list_fields(
            data,
            [
                ModelConverter.ExtractFieldParam("devices", "id", "device_ids"),
                ModelConverter.ExtractFieldParam("roles", "id", "role_ids"),
                ModelConverter.ExtractFieldParam("roles", "auth_key", "auth_keys"),
            ],
        )
        if isinstance(result, dict) and "address" in result:
            result["address"] = json.loads(result["address"]) if result["address"] is not None else []
        return result


class UserExport(SQLBaseModel, BaseUser):
    model_config = ConfigDict(from_attributes=True)

    last_login_datetime: datetime | None = Field(
        default=None, description="最后登录时间"
    )


class CurrentUser(UserOut):
    model_config = ConfigDict(from_attributes=True)
    # account_type: Optional[LoginAccountType] = Field(default=None, description="当前登录使用的账户类型")
    # device_id: Optional[IdType] = Field(default=None, description="当前登录使用设备的ID")


class UserLogin(BaseModel):
    """登录"""
    account: str = Field(description="账号")
    password: str = Field(description="密码")
    account_type: Optional[LoginAccountType] = Field(default=None,description="账户类型")

    @model_validator(mode="after")
    def validate_model(self)->Self:
        self.account_type = validate_account(self.account,self.account_type)
        validate_password(self.password,self.password)
        return self

class UserLoginOut(BaseModel):
    access_token: str = Field(description="账户Token")
    refresh_token: str = Field(description="刷新Token")
    token_type: str = Field(default="bearer", description="Token类型")


class UserUpdatePassword(BaseModel):
    """更新密码"""

    id: IdType
    password: str = Field(description="密码")
    confirm_password: str = Field(description="密码")
    new_password: str = Field(description="新密码")
    new_confirm_password: str = Field(description="新确认密码")

    @model_validator(mode="after")
    def validate_model(self)->Self:
        validate_password(self.password,self.confirm_password)
        validate_password(self.new_password,self.new_confirm_password)
        return self


class UserUpdateAvatar(BaseModel):
    """更新用户头像"""

    id: IdType
    avatar: str


class UserAssignPermission(BaseModel):
    id: IdType
    role_ids: list[IdType] | None = Field(description="角色ID列表")
